/*--------------------------------------------------------------------*\
FileName        : cbb_divider.v
Author          ：hpy
Email           ：yuan_hp@qq.com
Date            ：2025年05月14日
Description     ：任意整数分频器，根据用户输入的分频参数个数，模块自动增加分频器

1.例化
cbb_dividers #(
    .ENABLE_SQUARE(0),// 是否使能即便奇数分频也输出方波
    .DIVISORS({32'd5,     32'd10,    32'd15})  // 配置多个分频系数,每个数据必须时32bit的整数倍，输出个数为自动匹配
    //对应输出  o_clks[0]  o_clks[1]  o_clks[2]
) u_cbb_dividers (
    .i_clk(),    // 输入的系统时钟
    .i_rst_n(),  // 输入复位信号，低电平复位
    .o_clks()    // 输出分频后的时钟，位宽为
); 

或者

cbb_dividers #(
    .ENABLE_SQUARE(1),// 是否使能即便奇数分频也输出方波
    .DIVISORS({32'd5,     32'd10,    32'd15   , 32'd15 })  // 配置多个分频系数,每个数据必须时32bit的整数倍，输出个数为自动匹配
    //对应输出  o_clks[0]  o_clks[1]  o_clks[2]  o_clks[3]
) u_cbb_dividers (
    .i_clk(),    // 输入的系统时钟
    .i_rst_n(),  // 输入复位信号，低电平复位
    .o_clks()    // 输出分频后的时钟，位宽为
);

\*--------------------------------------------------------------------*/

`timescale 1ns / 1ps



module cbb_dividers #(
    parameter   DIVISORS      = {32'd5,32'd4,32'd5} , // 分频系数数组，默认值为 {5}
    parameter   ENABLE_SQUARE = 0,                  // 分频输出是否为方波，主要针对计数分频，非0时表示奇数分频也会输出方波
    parameter   NUM_OUTPUTS  = DIVISORS<=1?1:$clog2(DIVISORS)/32 +($clog2(DIVISORS) %32 ? 1:0 ) // 这个参数用户不要设置，否则模块工作异常
)(
    input i_clk,     // 输入信号
    input i_rst_n,
    output [NUM_OUTPUTS-1:0] o_clks   // 多个输出信号
);

initial begin 
    if(NUM_OUTPUTS != (DIVISORS<=1?1:$clog2(DIVISORS)/32 +($clog2(DIVISORS) %32 ? 1:0 ))  )begin
        $error("User should not set parameter NUM_OUTPUTS,IDE will can auto caculate!");
        $finish;
        $stop;
    end
end 

genvar i,j;
generate
    if(ENABLE_SQUARE)begin:SQUIRE
        for(i=NUM_OUTPUTS;i>0;i=i-1)begin:cbb_divider_inst
            cbb_divider #(
                .DIVISOR(DIVISORS[32*i - 1:32*(i-1)])
            ) u1 (
                .i_clk(i_clk),
                .i_rst_n(i_rst_n),
                .o_clk(o_clks[NUM_OUTPUTS-i])
            ); 
        end
    end else begin:NO_SQUIRE
        for(i=NUM_OUTPUTS;i>0;i=i-1)begin:cbb_divider_syncclk_inst
            cbb_divider_syncclk #(
                .DIVISOR(DIVISORS[32*i - 1:32*(i-1)])
            ) u2 (
                .i_clk(i_clk),
                .i_rst_n(i_rst_n),
                .o_clk(o_clks[NUM_OUTPUTS-i])
            ); 
        end
    end
endgenerate



`ifdef  CBB_SIM 
`include "cbb_sim.v"
initial begin 
    `CBB_SIM_LOG(("DIVISORS=%x  NUM_OUTPUTS=%d",DIVISORS , NUM_OUTPUTS)) ;
end
`endif 

endmodule